package org.carabiner.infinitest;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.StringWriter;

/**
 * 
 * @author <a href="mailto:benrady@gmail.com"Ben Rady</a>
 */
public class InfinitestUtils
{
  private static final String LINE_BREAK = "<br/>";

  public static String stackTraceToHTML(StackTraceElement[] stackTrace)
  {
    StringBuilder trace = new StringBuilder();
    trace.append("<html>");
    for(StackTraceElement element : stackTrace)
    {
      trace.append(element.toString() + LINE_BREAK);
    }    
    trace.setLength(trace.length() - LINE_BREAK.length());
    trace.append("</html>");
    return trace.toString();
  }
  
  public static String throwableToString(Throwable throwable)
  {
    String lineSep = System.getProperty("line.separator");
    String stackTrace = throwable.getMessage();
    stackTrace = stackTrace + lineSep;
    stackTrace = stackTrace + stackTraceToString(throwable.getStackTrace());    
    if (throwable.getCause() != null)
    {
      stackTrace = stackTrace + lineSep + "Caused By:" + lineSep;      
      stackTrace = stackTrace + throwableToString(throwable.getCause());
    }
    return stackTrace;
  }
  
  public static String stackTraceToString(StackTraceElement[] stackTrace)
  {
    StringBuilder trace = new StringBuilder();
    String lineSep = System.getProperty("line.separator");
    for(StackTraceElement element : stackTrace)
    {      
      trace.append(element.toString() + lineSep);
    }    
    trace.setLength(trace.length() - lineSep.length());    
    return trace.toString();
  }

  public static void touch(Class classToModify) throws IOException, InterruptedException
  {    
    File file = getFileForClass(classToModify);
    InputStream inStream = new FileInputStream(file);
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    copyStreams(inStream, outStream);
    outStream.flush();
    byte[] bytes = outStream.toByteArray();
    inStream = new ByteArrayInputStream(bytes);
    FileOutputStream foStream = new FileOutputStream(file, false);
    copyStreams(inStream, foStream);    
    Thread.sleep(100);
  }

  public static File getFileForClass(Class classToModify)
  {
    String classname = classToModify.getName(); 
    classname = classname.replace(".", "/");
    File file = new File(InfinitestSettings.getBuildPath() + "/" + classname + ".class");
    if (!file.exists())
      throw new IllegalArgumentException(file + " does not exist");
    return file;
  }  

  public static void copyStreams(InputStream in, OutputStream out) throws IOException
  {
    // Transfer bytes from in to out
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    in.close();
    out.flush();
    if (out instanceof FileOutputStream)
      ((FileOutputStream)out).getFD().sync();
    out.close();    
  }
}
